#include "CAnnouncementsPanel.h"
#include "CGamePanel.h"
#include "CItem.h"
#include "CPlayer.h"
#include "CPlayerInfoPanel.h"
#include "CTurnSchedule.h"
#include "Utils.h"

#include "CGame.h"

int CGame::run()
{
	int keyboardRepeatInitialDelay = 250;
	int keyboardRepeatInterval = 50;

	std::ifstream configFile("data/config");
	if (configFile.is_open())
	{
		std::string line;
		std::map<std::string, std::string> config;
		while (!configFile.eof())
		{
			std::string key, value;
			getline(configFile, line);

			size_t found = line.find("=");
			if (found != std::string::npos)
			{
				key = line.substr(0, found);
				value = line.substr(found+1);

				config[key] = value;
			}
		}

		configFile.close();

		if (config["KeyboardRepeatInitialDelay"] != "")
		{
			std::stringstream stream(config["KeyboardRepeatInitialDelay"]);
			stream >> keyboardRepeatInitialDelay;
		}

		if (config["KeyboardRepeatInterval"] != "")
		{
			std::stringstream stream(config["KeyboardRepeatInterval"]);
			stream >> keyboardRepeatInterval;
		}
	}

	TCODConsole::setCustomFont("data/terminal8x8_aa_ro.png", TCOD_FONT_LAYOUT_ASCII_INROW);
	TCODConsole::initRoot(80, 50, "Stone and Steel v0.1");
	TCODConsole::setKeyboardRepeat(keyboardRepeatInitialDelay, keyboardRepeatInterval);

	CItem::loadBaseItems();
	CItem::loadMaterials();
	CEntity::loadRaces();

	StateGetPlayerName();
	StateGetPlayerRace();

	CAnnouncementsPanel::init(rect(0, 40, 80, 10));
	CGamePanel::init(rect(0, 0, 50, 40));
	CPlayerInfoPanel::init(rect(50, 0, 30, 40));

	Dungeon = new CDungeon();
	Dungeon->generate(2, pair(100, 100));

    gPlayer->setAttribute("Strength", 16);
    gPlayer->setAttribute("Endurance", 16);
    gPlayer->init(gPlayer->getRace());
    gPlayer->setShape('@');

	CTurnSchedule::scheduleTurn(0, gPlayer); // Schedule for Players first turn

	TCODConsole::root->clear();
	CAnnouncementsPanel::draw();
	CGamePanel::draw(gPlayer->getShape(), gPlayer->getPosition(), gPlayer->getSight(), Dungeon->getFloor(gPlayer->getCurrentFloor()));
	CPlayerInfoPanel::draw();
	TCODConsole::root->flush();

	while (!gPlayer->readyToQuit() && !TCODConsole::isWindowClosed())
	{
		Dungeon->getFloor(gPlayer->getCurrentFloor())->update();
		CTurnSchedule::nextTurn();

		TCODConsole::root->clear();
		CAnnouncementsPanel::draw();
		CGamePanel::draw(gPlayer->getShape(), gPlayer->getPosition(), gPlayer->getSight(), Dungeon->getFloor(gPlayer->getCurrentFloor()));
		CPlayerInfoPanel::draw();
		TCODConsole::root->flush();
	}

	CAnnouncementsPanel::cleanup();
	CPlayerInfoPanel::cleanup();
	CGamePanel::cleanup();

	delete gPlayer;
	delete Dungeon;

	return 0;
}

CDungeon* CGame::getDungeon()
{
	return Dungeon;
}

void CGame::StateGetPlayerName()
{
	std::string name;
	std::string prompt = "What is your name? ";

	TCODConsole::root->clear();
	TCODConsole::root->print(3, 5, prompt.c_str());
	TCODConsole::root->flush();

	while (true)
	{
		TCOD_key_t key = TCODConsole::waitForKeypress(false);
		if (key.vk == TCODK_ENTER && name.size() > 0)
			break;
		else if (key.vk != TCODK_SHIFT && key.vk != TCODK_ENTER && key.vk != TCODK_BACKSPACE)
			name += key.c;
		else if (key.vk == TCODK_BACKSPACE && name.size() > 0)
			name.erase(name.end()-1);

		TCODConsole::root->clear();
		TCODConsole::root->print(3, 5, prompt.c_str());
		TCODConsole::root->print(3+prompt.size(), 5, name.c_str());
		TCODConsole::root->flush();
	}

	gPlayer = new CPlayer(name);
}

void CGame::StateGetPlayerRace()
{
	TCODConsole::root->clear();
	TCODConsole::root->print(4, 5, "Choose a race: ");
	unsigned int i = 6;
	for (std::map<std::string, SRace>::iterator itr = CEntity::Races.begin(); itr != CEntity::Races.end(); ++itr)
	{
		std::string raceline = "(";
		raceline += (*itr).second.Key;
		raceline += ") ";
		raceline += (*itr).first;

		TCODConsole::root->print(4, i, raceline.c_str());
		++i;
	}

	TCODConsole::root->flush();

    bool chosen = false;
	while (!chosen)
	{
		TCOD_key_t key = TCODConsole::waitForKeypress(true);
		for (std::map<std::string, SRace>::iterator itr = CEntity::Races.begin(); itr != CEntity::Races.end(); ++itr)
		    if (key.c == (*itr).second.Key)
		    {
		        gPlayer->setRace((*itr).first);
		        chosen = true;
		        break;
		    }
	}
}

CGame* gGame;

